# 导入相应的模块
import pygame
from pygame.locals import *
import time, random

class HeroPlane:
    '''玩家飞机'''
    def __init__(self, screen_temp):
        # 玩家飞机的大小106x76
        self.x = 203
        self.y = 522
        self.screen = screen_temp  # 获取已创建的窗口信息
        self.image = pygame.image.load("./image/me.png")
        self.bullet_list = []  # 用于存放玩家子弹的列表

    def display(self):
        # 绘制子弹
        for b in self.bullet_list:
            b.display()
            b.move()
            # 当子弹超出平面后，从类表中删除该子弹对象
            if b.move():
                self.bullet_list.remove(b)

        # 绘制玩家飞机
        self.screen.blit(self.image, (self.x, self.y))

    def move_left(self):
        '''左移动飞机'''
        self.x -= 5
        # 防止玩家飞机超出窗口左边界
        if self.x <= 0:
            self.x = 0

    def move_right(self):
        '''右移动飞机'''
        self.x += 5
        # 防止玩家飞机超出窗口有边界
        if self.x >= 406:
            self.x = 406

    def move_down(self):
        '''下移动飞机'''
        self.y += 5
        if self.y >= 524:
            self.y = 524

    def move_up(self):
        '''上移动飞机'''
        self.y -= 5
        if self.y <= 0:
            self.y = 0

    def fire(self):
        '''发射子弹'''
        # 每发射一次子弹，子弹列表里多一个子弹对象。子弹的初始位置为飞机当前的位置
        self.bullet_list.append(Bullet(self.screen, self.x, self.y))
        print(len(self.bullet_list))


class Bullet:
    '''子弹类'''
    def __init__(self, screen_temp, x, y):
        self.x = x+53  # 确保子弹从飞机中间发出
        self.y = y
        self.screen= screen_temp
        self.image = pygame.image.load("./image/pd.png")

    def display(self):
        '''绘制子弹'''
        self.screen.blit(self.image, (self.x, self.y))

    def move(self):
        '''子弹移动'''
        self.y -= 10
        if self.y <= -20:
            return True

class EnemyBullet:
    '''敌机子弹类'''
    def __init__(self, screen_temp, x, y):
        self.x = x + 49  # 确保子弹从飞机中间发出
        self.y = y + 76
        self.screen = screen_temp
        self.image = pygame.image.load("./image/pd2.png")

    def display(self):
        '''绘制子弹'''
        self.screen.blit(self.image, (self.x, self.y))

    def move(self):
        '''子弹移动'''
        self.y += 8
        if self.y >= 660:
            return True

class EnemyPlane:
    '''敌机类'''
    def __init__(self, screen_temp):
        self.x = random.choice(range(1, 414))  # 随机生成敌机的x坐标
        self.y = -80  # 敌机的初始位置在上边界之上
        self.screen= screen_temp
        self.image = pygame.image.load("./image/e1.png")  # 敌机像素98x76
        self.enemy_bullet_list = []  # 用于存放敌机子弹的列表

    def enemyfire(self):
        '''生成敌机子弹'''
        if random.choice(range(0, 30)) == 10:
            self.enemy_bullet_list.append(EnemyBullet(self.screen, self.x, self.y))


    def display(self):
        '''绘制敌机'''
        self.screen.blit(self.image, (self.x, self.y))
        # 调用生成敌机子弹的函数
        self.enemyfire()
        # 绘制敌机子弹
        for enb in self.enemy_bullet_list:
            enb.display()
            enb.move()

    def move(self, hero):
        '''敌机移动'''
        self.y += 3
        # 当敌机超出下边界时，move()返回真
        if self.y >= 700:
            return True
        # 遍历所有子弹，并执行碰撞检测，若碰撞，move()返回真
        for bu in hero.bullet_list:
            if bu.x > self.x and bu.x < self.x + 98 and bu.y > self.y + 38 and bu.y < self.y + 57:
                hero.bullet_list.remove(bu)  # 玩家子弹击中敌机后，击中敌机的子弹消失
                return True

    def bomb(self):
        '''敌机被击中后的爆炸效果'''
        # 导入爆炸图片
        bomb0 = pygame.image.load("./image/bo0.png")
        bomb1 = pygame.image.load("./image/bo1.png")
        bomb2 = pygame.image.load("./image/bo2.png")
        bomb3 = pygame.image.load("./image/bo3.png")
        for i in range(20):
            if 0 <= i <= 4:
                self.screen.blit(bomb0, (self.x, self.y))
            elif 5 <= i <= 9:
                self.screen.blit(bomb1, (self.x, self.y))
            elif 10 <= i <= 14:
                self.screen.blit(bomb1, (self.x, self.y))
            elif 15 <= i <= 19:
                self.screen.blit(bomb1, (self.x, self.y))


    def gameover(self):
        '''当敌机子弹击中玩家后，游戏结束'''
        for bu in self.enemy_bullet_list:
            if hero.x < bu.x < hero.x + 106 and hero.y + 15 < bu.y < hero.y +76:
                return True


def key_control(hero_temp):
    '''键盘控制函数'''
    # 执行退出操作
    for event in pygame.event.get():
        if event.type == QUIT:
            print("exit()")
            exit()
    # 获取按键信息
    pressed_key = pygame.key.get_pressed()
    # 做判断，并执行相应的操作
    if pressed_key[K_LEFT] or pressed_key[K_a]:
        print('Left')
        hero_temp.move_left()

    if pressed_key[K_RIGHT] or pressed_key[K_d]:
        print('Right')
        hero_temp.move_right()

    if pressed_key[K_UP] or pressed_key[K_w]:
        print('Up')
        hero_temp.move_up()

    if pressed_key[K_DOWN] or pressed_key[K_s]:
        print('Down')
        hero_temp.move_down()


    if pressed_key[K_SPACE]:
        print('Space')
        hero_temp.fire()




def main():
    '''主程序函数'''
    # 创建游戏窗口，窗口的分辨率为512x600
    screen = pygame.display.set_mode((512, 600), 0, 0)

    # 创建一个游戏背景，图片的像素为512x1536
    background = pygame.image.load("./image/bg2.jpg")

    end = pygame.image.load("./image/end1.png")

    # 实例化玩家飞机
    global hero
    hero = HeroPlane(screen)


    m = -936
    enemylist = []  # 存放敌机的列表
    while True:
        # 绘制画面(把图片的(0,0)点绑定在窗口中的某坐标上）
        screen.blit(background, (0, m))
        # 让图片滚动起来
        m += 1.5
        if m > -168:
            m = -936

        # 调用键盘控制函数
        key_control(hero)

        # 显示玩家飞机
        hero.display()


        # 随机绘制敌机
        if random.choice(range(0, 40)) == 10:
            enemylist.append(EnemyPlane(screen))
        # 遍历敌机并绘制移动
        for em in enemylist:
            em.display()
            # 当敌机超出屏幕下界或被玩家子弹击中时，将其从敌机列表中删除
            if em.move(hero):   # 将玩家对象传入move（为了获取玩家的子弹信息）
                enemylist.remove(em)
                em.bomb()
            # 当敌机子弹击中玩家后，游戏结束
            if em.gameover():
                screen.blit(end, (15, 200))
                pygame.display.update()
                time.sleep(10)
                exit()


        # 更新显示
        pygame.display.update()

        #定时显示
        time.sleep(0.03)  #每隔0.03秒更新一次画面（将程序的执行推迟0.03s）


# 判断当前是否是主运行程序，并调用
if __name__ == '__main__':
    main()
